package com.geeguo.ebuilder.client.controller.system.authorization;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import com.geeguo.ebuilder.client.base.core.dictionary.ClientTypeEnum;
import com.geeguo.ebuilder.client.base.redis.utils.CacheKeyFactory;
import com.geeguo.ebuilder.client.base.security.model.LoginUser;
import com.geeguo.ebuilder.client.base.security.utils.AuthUtils;
import com.geeguo.ebuilder.client.base.tenant.model.DataContext;
import com.geeguo.ebuilder.client.base.tenant.model.TenantInfo;
import com.geeguo.ebuilder.client.base.tenant.provider.TenantProvider;
import com.geeguo.ebuilder.client.business.system.authorization.model.CaptchaVO;
import com.geeguo.ebuilder.client.business.system.authorization.model.LoginDTO;
import com.geeguo.ebuilder.client.business.system.authorization.model.LoginVO;
import com.geeguo.ebuilder.client.business.system.authorization.service.AuthorizationService;
import com.geeguo.ebuilder.client.business.system.operlog.service.OperLogService;
import com.geeguo.ebuilder.client.business.system.permission.service.PermissionService;
import com.geeguo.ebuilder.client.business.system.user.model.UserEntity;
import com.geeguo.ebuilder.client.business.system.user.service.UserService;
import com.geeguo.ebuilder.core.common.action.ActionResult;
import com.geeguo.ebuilder.core.common.dictionary.StateEnum;
import com.geeguo.ebuilder.core.common.utils.key.UUIDGenerator;
import com.geeguo.ebuilder.core.redis.service.RedisCacheService;
import com.geeguo.ebuilder.core.security.annotation.RequiresLogin;
import com.geeguo.ebuilder.core.redis.constants.CacheTimeConstants;
import com.geeguo.ebuilder.core.security.constants.SecurityConstants;
import com.geeguo.ebuilder.core.security.exception.PasswordException;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.Date;

@Tag(name = "登录授权")
@RestController
public class AuthorizationController {

    @Autowired
    private UserService userService;
    @Autowired
    private OperLogService operLogService;
    @Autowired
    private PermissionService permissionService;
    @Autowired
    private RedisCacheService redisCacheService;
    @Autowired
    private AuthorizationService authorizationService;

    @Operation(summary = "登录")
    @PostMapping("/system/authorization/login")
    public ActionResult<LoginVO> login(@Validated @RequestBody LoginDTO dto, HttpServletRequest request) {
        if (StringUtils.isNotEmpty(dto.getUuid()) && StringUtils.isNotEmpty(dto.getCaptcha())) {
            String captcha = redisCacheService.get(CacheKeyFactory.INSTANCE.getCaptcha(dto.getUuid()));
            if (!dto.getCaptcha().equalsIgnoreCase(captcha)) {
                return ActionResult.fail("验证码错误");
            } else {
                // 删除验证码
                redisCacheService.del(CacheKeyFactory.INSTANCE.getCaptcha(dto.getUuid()));
            }
            DataContext dataContext = TenantProvider.getDataContext(dto.getTenantCode());
            UserEntity user = userService.getByCertificate(dto.getUsername(), dataContext);
            if (user == null && dto.getUsername().equals(SecurityConstants.SUPER_ADMIN_USERNAME)) {
                user = userService.initSuperAdmin(SecurityConstants.SUPER_ADMIN_USERNAME, dto.getPassword(), dataContext);
            }
            if (user != null) {
                if (user.getState() != null && user.getState() == StateEnum.Valid.getValue()) {
                    try {
                        if (authorizationService.checkPassword(user, dto.getPassword(), dataContext)) {
                            LoginUser loginUser = new LoginUser();
                            loginUser.setUserId(user.getId());
                            loginUser.setUsername(user.getUsername());
                            loginUser.setRealName(user.getRealName());
                            loginUser.setOrgId(user.getOrgId());
                            loginUser.setTenantCode(dataContext.getTenantCode());
                            loginUser.setClientType(ClientTypeEnum.Web.getValue());
                            permissionService.removeCachedUserWebModules(loginUser, dataContext);
                            loginUser.setRoles(permissionService.listRoleCodeByUser(loginUser, dataContext));
                            loginUser.setPermissions(permissionService.listPermissionCodeByUser(loginUser, dataContext));
                            AuthUtils.createToken(loginUser);
                            // 更新最后登录时间
                            userService.updateLastLogin(loginUser.getUserId(), dataContext);
                            // 记录登录日志
                            operLogService.saveLoginLog(loginUser, request, dataContext);
                            // 接口返回信息
                            LoginVO loginVO = new LoginVO();
                            loginVO.setAccessToken(loginUser.getToken());
                            loginVO.setUserId(loginUser.getUserId());
                            loginVO.setUsername(loginUser.getUsername());
                            loginVO.setRealName(loginUser.getRealName());
                            loginVO.setTenantCode(loginUser.getTenantCode());
                            loginVO.setRoles(loginUser.getRoles());
                            loginVO.setPermissions(loginUser.getPermissions());
                            return ActionResult.success(loginVO);
                        } else {
                            return ActionResult.fail("密码输入错误");
                        }
                    } catch (PasswordException e) {
                        return ActionResult.fail(e.getMessage());
                    }
                } else {
                    return ActionResult.fail("账号已被禁用");
                }
            } else {
                return ActionResult.fail("无效的账号");
            }
        } else {
            return ActionResult.fail("请输入验证码");
        }
    }

    @Operation(summary = "退出登录")
    @GetMapping("/system/authorization/logout")
    public ActionResult<Boolean> logout() {
        if (AuthUtils.getLoginUser() != null) {
            AuthUtils.logout();
        }
        return ActionResult.success(true);
    }

    @Operation(summary = "获取租户编码")
    @PostMapping(value = "/system/authorization/getTenantCode")
    public ActionResult<String> getTenantCode(@RequestParam("domain") String domain) {
        String tenantCode = null;
        if (StringUtils.isNotEmpty(domain)) {
            TenantInfo tenantInfo = TenantProvider.getByDomain(domain);
            if (tenantInfo != null) {
                tenantCode = tenantInfo.getCode();
            }
        }
        return ActionResult.success(tenantCode);
    }

    @Operation(summary = "获取验证码")
    @GetMapping(value = "/system/authorization/getCaptcha")
    public ActionResult<CaptchaVO> getCaptcha() {
        CaptchaVO result = new CaptchaVO();
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(150, 50, 4, 100);
        String captchaImageBase64 = lineCaptcha.getImageBase64();
        result.setImage(captchaImageBase64);
        result.setId(UUIDGenerator.getId());
        redisCacheService.set(CacheKeyFactory.INSTANCE.getCaptcha(result.getId()), lineCaptcha.getCode(), CacheTimeConstants.CAPTCHA);
        return ActionResult.success(result);
    }

    @Operation(summary = "更新用户个人密码")
    @PostMapping("/system/authorization/updatePassword")
    @RequiresLogin
    public ActionResult<Boolean> updatePassword(@RequestParam("password") String password) {
        LoginUser currentUser = AuthUtils.getLoginUser();
        DataContext dataContext = TenantProvider.getDataContext();
        if (userService.updatePassword(currentUser.getUserId(), password, new Date(), currentUser.getUserId(), dataContext)) {
            return ActionResult.success();
        }
        return ActionResult.fail();
    }
}